from pathlib import Path
import os
import pandas as pd
from moviepy.editor import VideoFileClip
import cv2
import time
import uuid  # 添加uuid模块导入


# from faster_whisper import WhisperModel

class VideoProcessor:
    def __init__(self, model_size="large-v2", device="cpu", compute_type="int8"):
        """初始化视频处理器
        
        参数:
            model_size: Whisper模型大小
            device: 运行设备 ("cpu" 或 "cuda")
            compute_type: 计算类型 ("int8", "float16" 等)
        """
        self.model = None
        self.model_size = model_size
        self.device = device
        self.compute_type = compute_type

    def split_video(self, video_path, output_dir, max_duration=3600):
        """将长视频切割成较短的片段
        
        参数:
            video_path: 视频文件路径
            output_dir: 输出目录
            max_duration: 每个片段的最大时长（秒），默认为1小时
            
        返回:
            list: 切割后的视频文件路径列表
        """
        try:
            # 确保输出目录存在
            os.makedirs(output_dir, exist_ok=True)

            # 加载视频文件
            video = VideoFileClip(video_path)
            total_duration = video.duration
            video_path_obj = Path(video_path)

            # 如果视频时长小于最大时长，则不需要切割
            if total_duration <= max_duration:
                print(f"视频时长为 {total_duration:.2f} 秒，不需要切割")
                return [video_path]

            # 计算需要切割的片段数
            num_segments = int(total_duration / max_duration) + (1 if total_duration % max_duration > 0 else 0)
            print(f"视频总时长为 {total_duration:.2f} 秒，将切割为 {num_segments} 个片段")

            # 切割视频
            segment_paths = []
            for i in range(num_segments):
                start_time = i * max_duration
                end_time = min((i + 1) * max_duration, total_duration)

                # 创建子片段
                segment = video.subclip(start_time, end_time)

                # 设置输出文件路径
                segment_filename = f"{video_path_obj.stem}_part{i + 1:02d}{video_path_obj.suffix}"
                segment_path = os.path.join(output_dir, segment_filename)

                # 保存片段
                segment.write_videofile(segment_path, codec="libx264", audio_codec="aac")
                segment_paths.append(segment_path)

                print(f"已保存片段 {i + 1}/{num_segments}: {segment_path} ({end_time - start_time:.2f} 秒)")

            # 关闭原始视频
            video.close()

            return segment_paths
        except Exception as e:
            print(f"视频切割过程中出现错误: {e}")
            return []

    def merge_csv_results(self, csv_paths, output_csv_path):
        """合并多个CSV结果文件
        
        参数:
            csv_paths: CSV文件路径列表
            output_csv_path: 输出CSV文件路径
            
        返回:
            bool: 是否成功合并
        """
        try:
            # 读取并合并所有CSV文件
            all_data = []
            time_offset = 0  # 时间偏移量（秒）

            for csv_path in csv_paths:
                # 读取CSV文件
                df = pd.read_csv(csv_path)

                # 调整时间戳
                if time_offset > 0:
                    adjusted_timestamps = []
                    for timestamp in df['timestamp']:
                        start_time, end_time = self._parse_timestamp(timestamp)
                        # 将毫秒转换为秒并添加偏移量
                        start_time_sec = start_time / 1000 + time_offset
                        end_time_sec = end_time / 1000 + time_offset
                        # 格式化为新的时间戳
                        new_timestamp = f"{self._format_time(start_time_sec)}-->{self._format_time(end_time_sec)}"
                        adjusted_timestamps.append(new_timestamp)

                    df['timestamp'] = adjusted_timestamps

                # 添加到总数据中
                all_data.append(df)

                # 更新时间偏移量（使用最后一个时间戳的结束时间）
                if not df.empty:
                    last_timestamp = df['timestamp'].iloc[-1]
                    _, last_end_time = self._parse_timestamp(last_timestamp)
                    time_offset = last_end_time / 1000  # 转换为秒

            # 合并所有数据
            if all_data:
                merged_df = pd.concat(all_data, ignore_index=True)
                merged_df.to_csv(output_csv_path, index=False)
                print(f"成功合并 {len(csv_paths)} 个CSV文件到 {output_csv_path}")
                return True
            else:
                print("没有有效的CSV数据可合并")
                return False
        except Exception as e:
            print(f"合并CSV文件过程中出现错误: {e}")
            return False

    def extract_audio(self, video_path, audio_path):
        """
        从视频中提取音频
        
        参数:
            video_path: 视频文件路径
            audio_path: 输出音频文件路径
        
        返回:
            bool: 是否成功提取
        """
        try:
            # 处理包含中文的文件路径
            audio_dir = os.path.dirname(audio_path)
            audio_filename = os.path.basename(audio_path)

            # 创建音频目录（如果不存在）
            os.makedirs(audio_dir, exist_ok=True)

            # 使用临时ASCII文件名
            temp_audio_path = os.path.join(audio_dir, f"temp_{int(time.time())}.mp3")

            # 加载视频文件
            video = VideoFileClip(video_path)
            # 从视频中提取音频
            audio = video.audio
            # 保存音频为MP3文件（使用临时文件名）
            audio.write_audiofile(temp_audio_path, codec='mp3')

            # 关闭资源
            audio.close()
            video.close()

            # 重命名为原始文件名
            if os.path.exists(audio_path):
                os.remove(audio_path)
            os.rename(temp_audio_path, audio_path)

            print(f"成功将 {video_path} 转换为 {audio_path}")
            return True
        except Exception as e:
            print(f"音频提取过程中出现错误: {e}")
            return False

    def audio_to_text(self, audio_path, output_csv_path):
        """
        将音频转换为带时间戳的文本
        
        参数:
            audio_path: 音频文件路径
            output_csv_path: 输出CSV文件路径
        
        返回:
            bool: 是否成功转换
        """
        try:
            self._load_model()

            # 转录音频
            segments, info = self.model.transcribe(audio_path, beam_size=5)
            print(f"检测到语言 '{info.language}' 置信度 {info.language_probability}")

            # 处理转录结果
            data = []
            for segment in segments:
                start_time = self._format_time(segment.start)
                end_time = self._format_time(segment.end)
                timestamp = f"{start_time}-->{end_time}"
                sentence = segment.text
                data.append({'timestamp': timestamp, 'sentence': sentence})

            # 保存为CSV
            df = pd.DataFrame(data)
            df.to_csv(output_csv_path, index=False)
            print(f"成功将音频转换为文本并保存到 {output_csv_path}")
            return True
        except Exception as e:
            print(f"音频转文本过程中出现错误: {e}")
            return False

    def extract_audio_clips_from_dataframe(self, video_path, df, output_dir, ip_id, progress_callback=None):
        """从DataFrame中提取音频片段，对应每个台词的时间段
        
        参数:
            video_path: 视频文件路径
            df: 包含时间戳和字幕的DataFrame
            output_dir: 输出目录
            ip_id: IP数据集ID（必填）
            progress_callback: 进度回调函数，用于更新子进度条
        
        返回:
            bool: 是否成功提取
        """
        try:
            # 创建输出目录
            os.makedirs(output_dir, exist_ok=True)
            # 创建audio_id列（如果不存在）
            if 'audio_id' not in df.columns:
                df['audio_id'] = ""

            # 加载视频文件
            video = VideoFileClip(video_path)
            if not video:
                raise IOError("无法打开视频文件")

            # 创建有效行的列表，用于计算进度
            valid_rows = []
            for index, row in df.iterrows():
                timestamp = row['timestamp']
                # 检查是否是有效的行
                try:
                    self._parse_timestamp(timestamp)
                    valid_rows.append((index, row))
                except ValueError:
                    continue

            total_valid_rows = len(valid_rows)

            # 处理每一行数据
            for i, (index, row) in enumerate(valid_rows):
                # 更新子进度条
                if progress_callback:
                    progress_callback(i / total_valid_rows)

                timestamp = row['timestamp']
                sentence = row['sentence']

                try:
                    start_ms, end_ms = self._parse_timestamp(timestamp)
                except ValueError as e:
                    print(f"跳过行 {index + 1}: {e}")
                    continue

                # print(f"\n处理: '{sentence}' ({timestamp})")
                # print(f"时间段: {start_ms}ms - {end_ms}ms")

                audio_id = str(uuid.uuid4().hex[:8])  # 使用uuid的前8位作为唯一标识符
                # 将audio_id添加到DataFrame中
                df.at[index, 'audio_id'] = audio_id

                # 提取音频片段
                start_sec = start_ms / 1000  # 转换为秒
                start_sec = max(0, start_sec - 0.5)
                end_sec = end_ms / 1000  # 转换为秒
                end_sec = min(end_sec + 0.5, video.duration)  # 延迟0.5s

                # 确保时间范围在视频时长内
                if end_sec > video.duration:
                    print(f"警告: 结束时间 {end_sec}秒 超出视频时长 {video.duration}秒，将调整为视频结束时间")
                    end_sec = video.duration

                if start_sec < end_sec:
                    # 提取音频片段
                    audio_clip = video.subclip(start_sec, end_sec).audio

                    # 保存音频片段
                    audio_path = os.path.join(output_dir, f"{audio_id}.mp3")
                    audio_clip.write_audiofile(audio_path, codec='mp3', verbose=False, logger=None)
                    # print(f"提取了音频片段: {audio_path}")

            # 完成后更新进度为100%
            if progress_callback:
                progress_callback(1.0)

            video.close()
            print("\n音频片段提取处理完成!")
            return True
        except Exception as e:
            print(f"音频片段提取过程中出现错误: {e}")
            return False

    def extract_frames_from_dataframe(self, video_path, df, output_dir, ip_id, progress_callback=None):
        """从DataFrame中提取视频帧，对应每个台词的中间帧
        
        参数:
            video_path: 视频文件路径
            df: 包含时间戳和字幕的DataFrame
            output_dir: 输出目录
            ip_id: IP数据集ID（必填）
            progress_callback: 进度回调函数，用于更新子进度条
        
        返回:
            bool: 是否成功提取
        """
        try:
            os.makedirs(output_dir, exist_ok=True)
            if 'image_id' not in df.columns:
                df['image_id'] = ""
            # 打开视频文件
            cap = cv2.VideoCapture(video_path)
            if not cap.isOpened():
                raise IOError("无法打开视频文件")

            # 获取视频信息
            fps = cap.get(cv2.CAP_PROP_FPS)
            total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
            duration = total_frames / fps if fps > 0 else 0

            print(f"视频信息: FPS={fps}, 总帧数={total_frames}, 时长={duration}秒")

            # 创建有效行的列表，用于计算进度
            valid_rows = []
            for index, row in df.iterrows():
                timestamp = row['timestamp']
                # 检查是否是有效的行
                try:
                    self._parse_timestamp(timestamp)
                    valid_rows.append((index, row))
                except ValueError:
                    continue

            total_valid_rows = len(valid_rows)
            print(f"需要处理的有效行数: {total_valid_rows}")

            # 处理每一行数据
            for i, (index, row) in enumerate(valid_rows):
                # 更新子进度条
                if progress_callback:
                    progress_callback(i / total_valid_rows)

                timestamp = row['timestamp']

                try:
                    start_ms, end_ms = self._parse_timestamp(timestamp)
                except ValueError as e:
                    print(f"跳过行 {index + 1}: {e}")
                    continue

                # print(f"\n处理: '{sentence}' ({timestamp})")
                # print(f"时间段: {start_ms}ms - {end_ms}ms")

                # 计算中间帧的时间点
                mid_time_ms = (start_ms + end_ms) / 2
                mid_time_sec = mid_time_ms / 1000  # 转换为秒

                # 计算对应的帧号
                frame_number = int(mid_time_sec * fps)

                # 确保帧号在有效范围内
                if frame_number >= total_frames:
                    print(f"警告: 计算的帧号 {frame_number} 超出总帧数 {total_frames}，将使用最后一帧")
                    frame_number = total_frames - 1

                # 跳转到指定帧
                cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
                ret, frame = cap.read()

                if not ret:
                    print(f"警告: 无法读取帧 {frame_number}，跳过")
                    continue

                # 修改为使用uuid
                image_id = str(uuid.uuid4().hex[:8])
                # 将image_id添加到DataFrame中
                df.at[index, 'image_id'] = image_id

                # 保存图片
                image_path = os.path.join(output_dir, f"{image_id}.jpg")
                cv2.imwrite(image_path, frame)
                # print(f"提取了中间帧: {image_path} (帧号: {frame_number})")

            # 完成后更新进度为100%
            if progress_callback:
                progress_callback(1.0)

            cap.release()
            print("\n视频帧提取处理完成!")
            return True
        except Exception as e:
            print(f"视频帧提取过程中出现错误: {e}")
            return False

    def process_video(self, video_path, output_dir=None):
        """处理视频的简化流程：提取音频、生成LRC字幕
        
        参数:
            video_path: 视频文件路径
            output_dir: 输出目录，默认为视频所在目录下的同名文件夹
        
        返回:
            bool: 是否成功处理
        """
        try:
            # 设置输出目录
            video_path = Path(video_path)
            if output_dir is None:
                output_dir = video_path.parent / video_path.stem

            output_dir = Path(output_dir)
            os.makedirs(output_dir, exist_ok=True)

            # 设置子目录
            audio_dir = output_dir / "audio"
            os.makedirs(audio_dir, exist_ok=True)

            # 设置文件路径
            audio_path = audio_dir / f"{video_path.stem}.mp3"
            lrc_path = output_dir / f"{video_path.stem}.lrc"

            # 1. 提取音频
            if not self.extract_audio(str(video_path), str(audio_path)):
                return False

            # 2. 音频转LRC字幕
            if not self.audio_to_lrc(str(audio_path), str(lrc_path)):
                return False

            print(f"\n视频处理完成! LRC字幕文件保存在: {lrc_path}")
            return True
        except Exception as e:
            print(f"视频处理过程中出现错误: {e}")
            return False

    def _format_time(self, seconds):
        """
        将秒数格式化为时间戳字符串 (HH:MM:SS,mmm)
        """
        hours = int(seconds // 3600)
        minutes = int((seconds % 3600) // 60)
        seconds_remainder = seconds % 60
        milliseconds = int((seconds_remainder - int(seconds_remainder)) * 1000)
        return f"{hours:02d}:{minutes:02d}:{int(seconds_remainder):02d},{milliseconds:03d}"

    def _format_lrc_time(self, seconds):
        """
        将秒数格式化为LRC格式的时间戳字符串 [mm:ss.xx]
        """
        minutes = int(seconds // 60)
        seconds_remainder = seconds % 60
        return f"[{minutes:02d}:{seconds_remainder:06.2f}]"

    def _merge_lrc_files(self, lrc_paths, output_lrc_path, title):
        """
        合并多个LRC文件
        
        参数:
            lrc_paths: LRC文件路径列表
            output_lrc_path: 输出LRC文件路径
            title: LRC标题
            
        返回:
            bool: 是否成功合并
        """
        try:
            # 写入合并后的LRC文件
            with open(output_lrc_path, 'w', encoding='utf-8') as out_file:
                # 写入LRC头部信息
                out_file.write(f"[ti:{title}]\n")
                out_file.write(f"[re:Auto Video Extract]\n")
                out_file.write(f"[ve:1.0]\n\n")

                # 读取并合并所有LRC文件的内容（跳过头部信息）
                time_offset = 0  # 时间偏移量（秒）

                for lrc_path in lrc_paths:
                    lines = []
                    with open(lrc_path, 'r', encoding='utf-8') as in_file:
                        # 跳过头部信息
                        for line in in_file:
                            line = line.strip()
                            if not line or line.startswith('[ti:') or line.startswith('[re:') or line.startswith(
                                    '[ve:'):
                                continue
                            lines.append(line)

                    # 调整时间戳并写入
                    for line in lines:
                        if line.startswith('['):
                            # 解析时间戳 [mm:ss.xx]
                            time_part = line[:line.find(']') + 1]
                            text_part = line[line.find(']') + 1:]

                            # 提取分钟和秒
                            time_str = time_part[1:-1]  # 去掉方括号
                            minutes, seconds = time_str.split(':')

                            # 计算总秒数并添加偏移量
                            total_seconds = int(minutes) * 60 + float(seconds) + time_offset

                            # 格式化为新的时间戳
                            new_time_tag = self._format_lrc_time(total_seconds)

                            # 写入调整后的行
                            out_file.write(f"{new_time_tag}{text_part}\n")

                    # 更新时间偏移量（使用最后一行的时间）
                    if lines and lines[-1].startswith('['):
                        last_time_part = lines[-1][:lines[-1].find(']') + 1]
                        last_time_str = last_time_part[1:-1]  # 去掉方括号
                        last_minutes, last_seconds = last_time_str.split(':')
                        time_offset = int(last_minutes) * 60 + float(last_seconds)

            print(f"成功合并 {len(lrc_paths)} 个LRC文件到 {output_lrc_path}")
            return True
        except Exception as e:
            print(f"合并LRC文件过程中出现错误: {e}")
            return False

    def _csv_to_lrc(self, csv_path, lrc_path, title):
        """
        将CSV格式的字幕文件转换为LRC格式
        
        参数:
            csv_path: CSV文件路径
            lrc_path: 输出LRC文件路径
            title: LRC标题
        
        返回:
            bool: 是否成功转换
        """
        try:
            # 读取CSV文件
            df = pd.read_csv(csv_path)

            # 写入LRC文件
            with open(lrc_path, 'w', encoding='utf-8') as f:
                # 写入LRC头部信息
                f.write(f"[ti:{title}]\n")
                f.write(f"[re:Auto Video Extract]\n")
                f.write(f"[ve:1.0]\n\n")

                # 写入字幕内容
                for _, row in df.iterrows():
                    timestamp = row['timestamp']
                    sentence = row['sentence']

                    # 解析时间戳
                    try:
                        start_ms, _ = self._parse_timestamp(timestamp)
                        # 转换为秒
                        start_sec = start_ms / 1000
                        # 格式化为LRC时间标签
                        time_tag = self._format_lrc_time(start_sec)
                        # 写入LRC行
                        f.write(f"{time_tag}{sentence}\n")
                    except ValueError as e:
                        print(f"跳过行: {e}")
                        continue

            print(f"成功将CSV转换为LRC字幕并保存到 {lrc_path}")
            return True
        except Exception as e:
            print(f"CSV转LRC过程中出现错误: {e}")
            return False

    def audio_to_lrc(self, audio_path, output_lrc_path):
        """
        将音频转换为LRC格式的字幕文件
        
        参数:
            audio_path: 音频文件路径
            output_lrc_path: 输出LRC文件路径
        
        返回:
            bool: 是否成功转换
        """
        try:
            self._load_model()

            # 转录音频
            segments, info = self.model.transcribe(audio_path, beam_size=5)
            print(f"检测到语言 '{info.language}' 置信度 {info.language_probability}")

            # 获取视频文件名作为标题
            title = Path(output_lrc_path).stem

            # 写入LRC文件
            with open(output_lrc_path, 'w', encoding='utf-8') as f:
                # 写入LRC头部信息
                f.write(f"[ti:{title}]\n")
                f.write(f"[re:Auto Video Extract]\n")
                f.write(f"[ve:1.0]\n\n")

                # 写入字幕内容
                for segment in segments:
                    time_tag = self._format_lrc_time(segment.start)
                    f.write(f"{time_tag}{segment.text}\n")

            print(f"成功将音频转换为LRC字幕并保存到 {output_lrc_path}")
            return True
        except Exception as e:
            print(f"音频转LRC字幕过程中出现错误: {e}")
            return False

    def _parse_timestamp(self, timestamp_str):
        """
        解析时间戳字符串为开始和结束时间（毫秒）
        """
        start_end = timestamp_str.split('-->')
        if len(start_end) != 2:
            raise ValueError(f"无效的时间戳格式: {timestamp_str}")

        start_time = start_end[0].strip()
        end_time = start_end[1].strip()

        def time_str_to_ms(time_str):
            hh_mm_ss, ms = time_str.split(',')
            h, m, s = hh_mm_ss.split(':')
            total_ms = int(h) * 3600 * 1000 + int(m) * 60 * 1000 + int(s) * 1000 + int(ms)
            return total_ms

        return time_str_to_ms(start_time), time_str_to_ms(end_time)

    def create_ip_metadata(self, ip_name, ip_id, output_path):
        """
        创建或更新IP元数据CSV文件
        
        参数:
            ip_name: IP数据集名称
            ip_id: IP数据集ID
            output_path: 输出CSV文件路径
        
        返回:
            bool: 是否成功创建或更新
        """
        try:
            # 创建新的IP元数据条目
            new_data = {
                'ip_id': ip_id,
                'ip_name': ip_name
            }

            # 确保输出目录存在
            os.makedirs(os.path.dirname(output_path), exist_ok=True)

            # 检查文件是否已存在
            if os.path.exists(output_path):
                # 读取现有数据
                existing_df = pd.read_csv(output_path)

                # 检查是否已存在相同的IP ID
                if not existing_df['ip_id'].str.contains(ip_id).any():
                    # 添加新数据到现有数据
                    new_row = pd.DataFrame([new_data])
                    updated_df = pd.concat([existing_df, new_row], ignore_index=True)
                    updated_df.to_csv(output_path, index=False)
                    print(f"成功更新IP元数据文件: {output_path}")
                    os.makedirs(os.path.join(output_path, ip_id), exist_ok=True)
                else:
                    print(f"IP ID {ip_id} 已存在于元数据文件中，无需更新")
            else:
                # 创建新文件
                df = pd.DataFrame([new_data])
                df.to_csv(output_path, index=False)
                print(f"成功创建IP元数据文件: {output_path}")

            return True
        except Exception as e:
            print(f"创建或更新IP元数据文件过程中出现错误: {e}")
            return False

    def create_subtitles_images_csv(self, csv_path, frames_dir, ip_id, output_path):
        """
        创建字幕与图片关联的CSV文件
        
        参数:
            csv_path: 原始字幕CSV文件路径
            frames_dir: 帧图片目录
            ip_id: IP数据集ID
            output_path: 输出CSV文件路径
        
        返回:
            bool: 是否成功创建
        """
        try:
            # 读取原始CSV文件
            df = pd.read_csv(csv_path)

            # 创建新的DataFrame
            data = []

            # 处理每一行数据
            for index, row in df.iterrows():
                timestamp = row['timestamp']
                sentence = row['sentence']

                # 解析时间戳
                try:
                    start_ms, end_ms = self._parse_timestamp(timestamp)
                except ValueError as e:
                    print(f"跳过行 {index + 1}: {e}")
                    continue

                # 创建图片ID和音频ID，使用相同的命名方式
                image_id = f"{ip_id}_{index + 1:04d}"
                audio_id = f"{ip_id}_{index + 1:04d}"

                # 添加到数据列表
                data.append({
                    'subtitle_id': index + 1,
                    'timestamp': timestamp,
                    'sentence': sentence,
                    'image_id': image_id,
                    'audio_id': audio_id,  # 添加音频ID字段
                    'ip_id': ip_id
                })

            # 保存为CSV
            new_df = pd.DataFrame(data)

            # 确保输出目录存在
            os.makedirs(os.path.dirname(output_path), exist_ok=True)

            new_df.to_csv(output_path, index=False)
            print(f"成功创建字幕与图片关联文件: {output_path}")
            return True
        except Exception as e:
            print(f"创建字幕与图片关联文件过程中出现错误: {e}")
            return False

    def merge_mp4_files(input_files, output_file, fps=None, resize_factor=None):
        """
        合并多个MP4文件为一个文件

        参数:
            input_files: MP4文件路径列表
            output_file: 输出文件路径
            fps: 输出视频的帧率，None表示保持原帧率
            resize_factor: 分辨率缩放因子(0-1)，None表示保持原分辨率

        返回:
            bool: 是否成功合并
        """
        try:
            # 检查输入文件是否存在
            for file_path in input_files:
                if not os.path.exists(file_path):
                    print(f"错误: 文件不存在 - {file_path}")
                    return False

            # 加载所有视频片段
            print(f"正在加载 {len(input_files)} 个视频文件...")
            video_clips = []

            for file_path in input_files:
                print(f"加载: {file_path}")
                clip = VideoFileClip(file_path)

                # 调整分辨率
                if resize_factor is not None and 0 < resize_factor < 1:
                    original_size = clip.size
                    new_width = int(original_size[0] * resize_factor)
                    new_height = int(original_size[1] * resize_factor)
                    print(f"调整分辨率: {original_size} -> ({new_width}, {new_height})")
                    # 修改这一行，使用fx方法应用resize效果
                    clip = clip.fx(vfx_resize, newsize=(new_width, new_height))

                video_clips.append(clip)

            # 合并视频片段
            print("正在合并视频...")
            final_clip = concatenate_videoclips(video_clips)

            # 调整帧率
            if fps is not None and fps > 0:
                original_fps = final_clip.fps
                print(f"调整帧率: {original_fps} -> {fps} fps")
                final_clip = final_clip.set_fps(fps)

            # 确保输出目录存在
            output_dir = os.path.dirname(output_file)
            if output_dir and not os.path.exists(output_dir):
                os.makedirs(output_dir, exist_ok=True)

            # 保存合并后的视频
            print(f"正在保存合并后的视频到: {output_file}")
            final_clip.write_videofile(output_file, codec="libx264", audio_codec="aac")

            # 关闭所有视频片段
            for clip in video_clips:
                clip.close()

            print("视频合并完成!")
            return True
        except Exception as e:
            print(f"视频合并过程中出现错误: {e}")
            return False

    def merge_folder_mp4_files(folder_path, output_file, sort_by='name', fps=None, resize_factor=None):
        """
        合并文件夹内的所有MP4文件

        参数:
            folder_path: 包含MP4文件的文件夹路径
            output_file: 输出文件路径
            sort_by: 文件排序方式，可选值：'name'(按文件名)、'time'(按修改时间)、'size'(按文件大小)
            fps: 输出视频的帧率，None表示保持原帧率
            resize_factor: 分辨率缩放因子(0-1)，None表示保持原分辨率

        返回:
            bool: 是否成功合并
        """
        try:
            # 检查文件夹是否存在
            if not os.path.isdir(folder_path):
                print(f"错误: 文件夹不存在 - {folder_path}")
                return False

            # 获取文件夹内所有MP4文件
            mp4_files = []
            for file in os.listdir(folder_path):
                if file.lower().endswith('.mp4'):
                    mp4_files.append(os.path.join(folder_path, file))

            if not mp4_files:
                print(f"错误: 文件夹内没有MP4文件 - {folder_path}")
                return False

            # 根据排序方式对文件进行排序
            if sort_by == 'name':
                mp4_files.sort()
            elif sort_by == 'time':
                mp4_files.sort(key=lambda x: os.path.getmtime(x))
            elif sort_by == 'size':
                mp4_files.sort(key=lambda x: os.path.getsize(x))

            for file in mp4_files:
                print(f"  - {os.path.basename(file)}")

            # 合并文件
            return merge_mp4_files(mp4_files, output_file, fps, resize_factor)

        except Exception as e:
            print(f"合并文件夹内视频过程中出现错误: {e}")
            return False
